package com.house365.updown.upload;

import java.io.File;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.james.mime4j.util.CharsetUtil;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import com.house365.core.constant.CorePreferences;
import com.house365.core.json.JSONObject;
import com.house365.updown.upload.CustomMultipartEntity.ProgressListener;

/**
 *@author py
 *@date 2013-7-19
 *@comment
 */
public class HttpUploaderManager {
	 public static final String ACTION_UPLOAD_COMPLETE = "android.author.cloud.download.UPLOAD_COMPLETE";
	 public static final String EXTRA_UPLOAD_ID = "extra_download_id";
	public Context mContext = null;

	public static final int MSG_UPLOAD_STATUS_COMPLETED = 0;
	public static final int MSG_UPLOAD_STATUS_ERROR = 1;
	private OnServerResponse onServerResponse;

	public Map<Long,UploaderInfo> uploaderInfos =new HashMap<Long,UploaderInfo>();
	
	public interface UploadListener{
		public void onComplete(long id,String response);
		public void onError(long id,String response);
	}

	public interface OnServerResponse{
		public boolean isSuccess(String response);
	}
	private UploadListener uploadListener;
	private HttpClient httpClient;
	private HttpContext httpContext;
	public HttpUploaderManager(Context context,OnServerResponse onServerResponse) {
		this.mContext = context;
		httpClient = createDefClient();  
        httpContext = new BasicHttpContext();  
		this.onServerResponse = onServerResponse;
		
	}
	public DefaultHttpClient createDefClient() {
		// Sets up the http part of the service.
		final SchemeRegistry supportedSchemes = new SchemeRegistry();

		// Register the "http" protocol scheme, it is required
		// by the default operator to look up socket factories.
		   
		   
		final SocketFactory sf = PlainSocketFactory.getSocketFactory();
		supportedSchemes.register(new Scheme("http", sf, 80));
		supportedSchemes.register(new Scheme("https", SSLSocketFactory
				.getSocketFactory(), 443));
		// Set some client http client parameter defaults.
		final HttpParams httpParams = createHttpParams();
		final ClientConnectionManager ccm = new ThreadSafeClientConnManager(
				httpParams, supportedSchemes);
		return new DefaultHttpClient(ccm, httpParams);
	}
	private final HttpParams createHttpParams() {
		final HttpParams params = new BasicHttpParams();
		HttpConnectionParams.setStaleCheckingEnabled(params, false);
		
		 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
		 HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

		return params;
	}
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			try {
				switch (msg.what) {
				case MSG_UPLOAD_STATUS_COMPLETED:{
					long id = (Long) msg.obj;
					UploaderInfo info = uploaderInfos.get(id);
					info.setStatus(UploaderInfo.UPLOAD_STATUS_COMPLETED);
					//notify complete
					if(uploadListener!= null){
						uploadListener.onComplete(id,info.getHttpReponse());
					}
					break;
				}
				case MSG_UPLOAD_STATUS_ERROR:{
					long id = (Long) msg.obj;
					UploaderInfo info = uploaderInfos.get(id);
					info.setStatus(UploaderInfo.UPLOAD_STATUS_ERROR);
					if(uploadListener!= null){
						uploadListener.onError(id,info.getHttpReponse());
					}
					break;
				}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};
	public UploaderInfo getUploaderInfo(long id){
		return uploaderInfos.get(id);
	}
	public void cancelUpload(long id){
		UploaderInfo info = uploaderInfos.get(id);
		try {
			info.getHttpPost().abort();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public int getUploadInfoStauts(long id){
		UploaderInfo info = uploaderInfos.get(id);
		return info.getStatus();
	}

	/**
	 * 
	 * 上传文件
	 * @param downloadMessage
	 * @param fileUrl
	 * @param filePath
	 */
	public long uploadFile(final UFile ufile) {
			CorePreferences.DEBUG("uploadFile,url:"+ufile.getRemoteFileUri()+",local:"+ufile.getLocalFileUri());
		//生成一个下载配置信息
		UploaderInfo uploaderInfo = new UploaderInfo();
		final long id = uploaderInfo.getId();
		uploaderInfos.put(id, uploaderInfo);
		
		// 启动进程下载
		new Thread(new Runnable() {
			public void run() {
				if (isUploadedFile(id, ufile.getRemoteFileUri(), ufile.getFileParam(), ufile.getLocalFileUri(), ufile.getExtralParam(), onServerResponse)) {
					Message msg = new Message();
					msg.what = MSG_UPLOAD_STATUS_COMPLETED;
					msg.obj = id;
					mHandler.sendMessage(msg);
				} else {
					Message msg = new Message();
					msg.what = MSG_UPLOAD_STATUS_ERROR;
					msg.obj = id;
					mHandler.sendMessage(msg);
				}
			}
		}).start();
		return id;
	}

	/***
	 * upload and return the flag whether download successful
	 * @param context
	 * @param strurl
	 * @param filename
	 * @return
	 */
	public boolean isUploadedFile(long id, final String url,final String fileParam,final String filePath,String extralParam,OnServerResponse onServerResponse) {
		return uploadFile(id, url, fileParam, filePath, extralParam, onServerResponse);
	}



	/**
	 * 上传文件
	 * @param id
	 * @param url
	 * @param fileParam,扩展字段，json对象key，value
	 * @param filePath
	 * @param extral
	 * @param onServerResponse
	 * @return
	 */
	private boolean uploadFile(long id,final String url,final String fileParam,final String filePath,String extralParam,OnServerResponse onServerResponse) {
		boolean bRet = false;

		HttpPost httpPost = new HttpPost(url);  
		httpPost.addHeader("charset", HTTP.UTF_8);

		  try {  
				final UploaderInfo info =  uploaderInfos.get(id);
	            CustomMultipartEntity multipartContent = new CustomMultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE,null, CharsetUtil
	            		.getCharset("UTF-8"),
	                    new ProgressListener() {  
	                        @Override  
	                        public void transferred(long num) {  
	                           //进度控制
	                        	info.setNowSize(num);
	                        }  
	                    });  
	            File f = new File(filePath);
	            
	            multipartContent.addPart(fileParam, new FileBody(f));  
	            //设置文件大小
	        	
	        	if(!TextUtils.isEmpty(extralParam)){
	        		//设置其他扩展参数
	        		JSONObject json = new JSONObject(extralParam);
	        		Iterator<String> keys = json.keys();
	        		while(keys.hasNext()){
	        			String key = keys.next();
	        			multipartContent.addPart(key,
			    				new StringBody(json.getString(key), Charset.forName(HTTP.UTF_8)));
	        		}
	        	}
	        	info.setMaxSize(multipartContent.getContentLength());  
	            //提交
	            httpPost.setEntity(multipartContent);  
	            info.setHttpPost(httpPost);
	            HttpResponse response = httpClient.execute(httpPost, httpContext);  
	            String charset = EntityUtils.getContentCharSet(response.getEntity()) == null ? HTTP.UTF_8
						: EntityUtils.getContentCharSet(response.getEntity());
				String httpReponse =  new String(EntityUtils.toByteArray(response.getEntity()), charset);
	            bRet = onServerResponse.isSuccess(httpReponse);
				info.setHttpReponse(httpReponse);
	        } catch (Exception e) {  
	            e.printStackTrace();  
	            bRet = false;
	        }  
		return bRet;
	}
	public UploadListener getUploadListener() {
		return uploadListener;
	}
	public void setUploadListener(UploadListener uploadListener) {
		this.uploadListener = uploadListener;
	}

}
